using CollabApp.Application.Interfaces;
using CollabApp.Domain.Entities.Game;
using CollabApp.Domain.Services.Game;
using Microsoft.Extensions.Logging;
using System.Text.Json;

namespace CollabApp.Application.Services.Game;

/// <summary>
/// 领土管理服务实现
/// 负责管理圈地游戏中的领土系统，包括画线轨迹、领地计算、圈地检测等
/// </summary>
public class TerritoryService : ITerritoryService
{
    private readonly IRedisService _redisService;
    private readonly ILogger<TerritoryService> _logger;

    /// <summary>
    /// Redis键格式
    /// </summary>
    private static class RedisKeys
    {
        public const string PlayerTrail = "player_trail:{0}:{1}"; // gameId:playerId
        public const string PlayerTerritory = "player_territory:{0}:{1}"; // gameId:playerId
        public const string PlayerState = "player_state:{0}:{1}"; // gameId:playerId
        public const string GamePlayers = "game_players:{0}"; // gameId
        public const string MapDistribution = "map_distribution:{0}"; // gameId
        public const string TerritoryBounds = "territory_bounds:{0}:{1}"; // gameId:playerId
    }

    /// <summary>
    /// 游戏常量
    /// </summary>
    private static class GameConstants
    {
        public const float MaxTrailLength = 500f; // 最大画线长度
        public const float MinTerritoryArea = 100f; // 最小有效领地面积
        public const float MapSize = 1000f; // 地图大小
        public const float MapTotalArea = MapSize * MapSize; // 地图总面积
        public const decimal DominantPlayerThreshold = 0.7m; // 优势玩家阈值70%
        public const float NearLimitThreshold = 0.8f; // 接近限制的阈值80%
    }

    /// <summary>
    /// 构造函数
    /// </summary>
    public TerritoryService(IRedisService redisService, ILogger<TerritoryService> logger)
    {
        _redisService = redisService ?? throw new ArgumentNullException(nameof(redisService));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    /// <summary>
    /// 开始画线
    /// </summary>
    public async Task<DrawingStartResult> StartDrawingAsync(Guid gameId, Guid playerId, Position startPosition)
    {
        try
        {
            _logger.LogInformation("开始画线 - GameId: {GameId}, PlayerId: {PlayerId}, Position: ({X},{Y})", 
                gameId, playerId, startPosition.X, startPosition.Y);

            // 验证起始位置是否合法（在玩家领地内或出生点）
            var ownership = await CheckTerritoryOwnershipAsync(gameId, startPosition, playerId);
            if (!ownership.IsOwned && !ownership.IsSpawnArea)
            {
                return new DrawingStartResult
                {
                    Success = false,
                    Errors = { "只能从自己的领地或出生点开始画线" }
                };
            }

            // 清空当前轨迹
            var trailKey = string.Format(RedisKeys.PlayerTrail, gameId, playerId);
            await _redisService.KeyDeleteAsync(trailKey);

            // 添加起始点
            var trailPoint = JsonSerializer.Serialize(new TrailPoint
            {
                Position = startPosition,
                Timestamp = DateTime.UtcNow,
                SequenceNumber = 0
            });
            await _redisService.ListRightPushAsync(trailKey, trailPoint);

            // 更新玩家状态为画线中
            var stateKey = string.Format(RedisKeys.PlayerState, gameId, playerId);
            await _redisService.SetHashAsync(stateKey, "state", PlayerDrawingState.Drawing.ToString());
            await _redisService.SetHashAsync(stateKey, "drawing_start_time", DateTime.UtcNow.ToString("O"));

            _logger.LogInformation("画线开始成功 - GameId: {GameId}, PlayerId: {PlayerId}", gameId, playerId);

            return new DrawingStartResult
            {
                Success = true,
                StartPosition = startPosition,
                StartTime = DateTime.UtcNow,
                Messages = { "开始画线" }
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "开始画线失败 - GameId: {GameId}, PlayerId: {PlayerId}", gameId, playerId);
            return new DrawingStartResult
            {
                Success = false,
                Errors = { "开始画线时发生内部错误" }
            };
        }
    }

    /// <summary>
    /// 更新画线轨迹
    /// </summary>
    public async Task<TrailUpdateResult> UpdateTrailAsync(Guid gameId, Guid playerId, Position newPosition)
    {
        try
        {
            _logger.LogDebug("更新画线轨迹 - GameId: {GameId}, PlayerId: {PlayerId}, Position: ({X},{Y})", 
                gameId, playerId, newPosition.X, newPosition.Y);

            var trailKey = string.Format(RedisKeys.PlayerTrail, gameId, playerId);
            
            // 获取当前轨迹
            var currentTrailData = await _redisService.ListRangeAsync(trailKey);
            var currentTrail = currentTrailData.Select(data =>
            {
                try
                {
                    var trailPoint = JsonSerializer.Deserialize<TrailPoint>(data);
                    return trailPoint?.Position ?? new Position();
                }
                catch
                {
                    return new Position();
                }
            }).ToList();

            // 计算当前轨迹长度
            var currentLength = CalculateTrailLength(currentTrail);
            
            // 检查是否会超过长度限制
            var distanceToAdd = currentTrail.Any() 
                ? CalculateDistance(currentTrail.Last(), newPosition) 
                : 0f;
            
            if (currentLength + distanceToAdd > GameConstants.MaxTrailLength)
            {
                return new TrailUpdateResult
                {
                    Success = false,
                    CurrentTrail = currentTrail,
                    TrailLength = currentLength,
                    ErrorMessage = $"画线长度超过限制：{currentLength + distanceToAdd:F1} > {GameConstants.MaxTrailLength}"
                };
            }

            // 添加新的轨迹点
            var newTrailPoint = JsonSerializer.Serialize(new TrailPoint
            {
                Position = newPosition,
                Timestamp = DateTime.UtcNow,
                SequenceNumber = currentTrail.Count
            });
            await _redisService.ListRightPushAsync(trailKey, newTrailPoint);

            // 更新后的轨迹
            currentTrail.Add(newPosition);
            var newLength = currentLength + distanceToAdd;
            var isNearLimit = newLength / GameConstants.MaxTrailLength > GameConstants.NearLimitThreshold;

            _logger.LogDebug("轨迹更新成功 - GameId: {GameId}, PlayerId: {PlayerId}, Length: {Length:F1}", 
                gameId, playerId, newLength);

            return new TrailUpdateResult
            {
                Success = true,
                TrailId = Guid.NewGuid(), // 模拟轨迹ID
                CurrentTrail = currentTrail,
                TrailLength = newLength,
                IsNearLimit = isNearLimit
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "更新画线轨迹失败 - GameId: {GameId}, PlayerId: {PlayerId}", gameId, playerId);
            return new TrailUpdateResult
            {
                Success = false,
                ErrorMessage = "更新轨迹时发生内部错误"
            };
        }
    }

    /// <summary>
    /// 完成圈地
    /// </summary>
    public async Task<TerritoryCompleteResult> CompleteTerritoryAsync(Guid gameId, Guid playerId, Position endPosition)
    {
        try
        {
            _logger.LogInformation("完成圈地 - GameId: {GameId}, PlayerId: {PlayerId}, EndPosition: ({X},{Y})", 
                gameId, playerId, endPosition.X, endPosition.Y);

            // 获取当前轨迹
            var trailKey = string.Format(RedisKeys.PlayerTrail, gameId, playerId);
            var currentTrailData = await _redisService.ListRangeAsync(trailKey);
            var currentTrail = currentTrailData.Select(data =>
            {
                try
                {
                    var trailPoint = JsonSerializer.Deserialize<TrailPoint>(data);
                    return trailPoint?.Position ?? new Position();
                }
                catch
                {
                    return new Position();
                }
            }).ToList();

            if (currentTrail.Count < 3)
            {
                return new TerritoryCompleteResult
                {
                    Success = false,
                    ErrorMessage = "轨迹点数不足，无法圈地"
                };
            }

            // 添加结束点形成闭合
            currentTrail.Add(endPosition);

            // 检查是否形成有效的闭合区域
            if (!IsValidClosedArea(currentTrail))
            {
                return new TerritoryCompleteResult
                {
                    Success = false,
                    ErrorMessage = "未形成有效的闭合区域"
                };
            }

            // 计算新领地面积
            var newArea = CalculatePolygonArea(currentTrail);
            if (newArea < GameConstants.MinTerritoryArea)
            {
                return new TerritoryCompleteResult
                {
                    Success = false,
                    ErrorMessage = $"圈地面积过小：{newArea:F1} < {GameConstants.MinTerritoryArea}"
                };
            }

            // 检查是否征服了其他玩家的领地
            var conquestResult = await CalculateTerritoryConquestAsync(gameId, playerId, currentTrail);

            // 获取玩家当前总面积
            var currentAreaInfo = await CalculatePlayerTerritoryAsync(gameId, playerId);
            var newTotalArea = currentAreaInfo.CurrentArea + (decimal)newArea + conquestResult.TotalConqueredArea;

            // 保存新领地
            await SavePlayerTerritoryAsync(gameId, playerId, currentTrail, newArea);

            // 清除轨迹
            await _redisService.KeyDeleteAsync(trailKey);

            // 更新玩家状态为空闲
            var stateKey = string.Format(RedisKeys.PlayerState, gameId, playerId);
            await _redisService.SetHashAsync(stateKey, "state", PlayerDrawingState.Idle.ToString());
            await _redisService.SetHashAsync(stateKey, "territory_area", newTotalArea.ToString("F2"));

            _logger.LogInformation("圈地完成 - GameId: {GameId}, PlayerId: {PlayerId}, Area: {Area:F1}, NewTotal: {Total:F1}", 
                gameId, playerId, newArea, newTotalArea);

            return new TerritoryCompleteResult
            {
                Success = true,
                AreaGained = (decimal)newArea,
                NewTotalArea = newTotalArea,
                NewTerritory = currentTrail,
                ConqueredPlayers = conquestResult.ConqueredPlayers,
                ConqueredArea = conquestResult.TotalConqueredArea
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "完成圈地失败 - GameId: {GameId}, PlayerId: {PlayerId}", gameId, playerId);
            return new TerritoryCompleteResult
            {
                Success = false,
                ErrorMessage = "完成圈地时发生内部错误"
            };
        }
    }

    /// <summary>
    /// 计算玩家领地面积
    /// </summary>
    public async Task<TerritoryAreaInfo> CalculatePlayerTerritoryAsync(Guid gameId, Guid playerId)
    {
        try
        {
            _logger.LogDebug("计算玩家领地面积 - GameId: {GameId}, PlayerId: {PlayerId}", gameId, playerId);

            var territoryKey = string.Format(RedisKeys.PlayerTerritory, gameId, playerId);
            var territoriesData = await _redisService.ListRangeAsync(territoryKey);

            var totalArea = 0m;
            var allBoundaries = new List<Position>();

            foreach (var territoryData in territoriesData)
            {
                try
                {
                    var territory = JsonSerializer.Deserialize<TerritoryPolygon>(territoryData);
                    if (territory != null)
                    {
                        totalArea += (decimal)territory.Area;
                        allBoundaries.AddRange(territory.Boundary);
                    }
                }
                catch (JsonException)
                {
                    // 忽略无效的领地数据
                }
            }

            // 计算面积百分比
            var areaPercentage = totalArea / (decimal)GameConstants.MapTotalArea * 100;

            // 计算领地中心
            var center = allBoundaries.Any() 
                ? new Position
                {
                    X = allBoundaries.Average(p => p.X),
                    Y = allBoundaries.Average(p => p.Y)
                }
                : new Position();

            // 获取排名（简化处理）
            var rank = await GetPlayerRankAsync(gameId, playerId);

            return new TerritoryAreaInfo
            {
                PlayerId = playerId,
                CurrentArea = totalArea,
                AreaPercentage = areaPercentage,
                Rank = rank,
                TerritoryBoundary = allBoundaries,
                Center = center
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "计算玩家领地面积失败 - GameId: {GameId}, PlayerId: {PlayerId}", gameId, playerId);
            return new TerritoryAreaInfo
            {
                PlayerId = playerId,
                CurrentArea = 0m
            };
        }
    }

    /// <summary>
    /// 检查位置是否在玩家领地内
    /// </summary>
    public async Task<TerritoryOwnership> CheckTerritoryOwnershipAsync(Guid gameId, Position position, Guid? playerId = null)
    {
        try
        {
            _logger.LogDebug("检查领地归属 - GameId: {GameId}, Position: ({X},{Y}), PlayerId: {PlayerId}", 
                gameId, position.X, position.Y, playerId);

            // 如果指定了玩家ID，只检查该玩家的领地
            if (playerId.HasValue)
            {
                var isOwnedByPlayer = await IsPositionInPlayerTerritoryAsync(gameId, playerId.Value, position);
                if (isOwnedByPlayer)
                {
                    var playerColor = await GetPlayerColorAsync(gameId, playerId.Value);
                    return new TerritoryOwnership
                    {
                        IsOwned = true,
                        OwnerId = playerId.Value,
                        OwnerColor = playerColor
                    };
                }
            }

            // 检查所有玩家的领地
            var playersKey = string.Format(RedisKeys.GamePlayers, gameId);
            var playerIds = await _redisService.GetSetMembersAsync(playersKey);

            foreach (var playerIdStr in playerIds)
            {
                if (Guid.TryParse(playerIdStr, out var checkPlayerId))
                {
                    var isOwnedByPlayer = await IsPositionInPlayerTerritoryAsync(gameId, checkPlayerId, position);
                    if (isOwnedByPlayer)
                    {
                        var playerColor = await GetPlayerColorAsync(gameId, checkPlayerId);
                        return new TerritoryOwnership
                        {
                            IsOwned = true,
                            OwnerId = checkPlayerId,
                            OwnerColor = playerColor
                        };
                    }
                }
            }

            // 检查是否为出生区域（简化处理）
            var isSpawnArea = await IsSpawnAreaAsync(gameId, position);

            return new TerritoryOwnership
            {
                IsOwned = false,
                IsNeutralZone = !isSpawnArea,
                IsSpawnArea = isSpawnArea,
                DistanceToNearestBoundary = await CalculateDistanceToNearestBoundaryAsync(gameId, position)
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "检查领地归属失败 - GameId: {GameId}, Position: ({X},{Y})", gameId, position.X, position.Y);
            return new TerritoryOwnership
            {
                IsOwned = false,
                IsNeutralZone = true
            };
        }
    }

    /// <summary>
    /// 重置玩家领地
    /// </summary>
    public async Task<TerritoryResetResult> ResetPlayerTerritoryAsync(Guid gameId, Guid playerId, decimal keepPercentage = 0.2m)
    {
        try
        {
            _logger.LogInformation("重置玩家领地 - GameId: {GameId}, PlayerId: {PlayerId}, KeepPercentage: {Percentage}", 
                gameId, playerId, keepPercentage);

            // 获取当前领地面积
            var currentAreaInfo = await CalculatePlayerTerritoryAsync(gameId, playerId);
            var lostArea = currentAreaInfo.CurrentArea * (1 - keepPercentage);
            var remainingArea = currentAreaInfo.CurrentArea * keepPercentage;

            // 清除大部分领地，只保留出生点附近的小安全区
            var territoryKey = string.Format(RedisKeys.PlayerTerritory, gameId, playerId);
            await _redisService.KeyDeleteAsync(territoryKey);

            // 获取出生点
            var spawnPoint = await GetPlayerSpawnPointAsync(gameId, playerId);

            // 创建小安全区
            var safeAreaSize = Math.Max(50f, (float)remainingArea * 0.1f);
            var safeArea = CreateSafeArea(spawnPoint, safeAreaSize);
            
            await SavePlayerTerritoryAsync(gameId, playerId, safeArea, safeAreaSize * safeAreaSize);

            // 更新玩家领地面积
            var stateKey = string.Format(RedisKeys.PlayerState, gameId, playerId);
            await _redisService.SetHashAsync(stateKey, "territory_area", remainingArea.ToString("F2"));

            _logger.LogInformation("领地重置完成 - GameId: {GameId}, PlayerId: {PlayerId}, Lost: {Lost:F1}, Remaining: {Remaining:F1}", 
                gameId, playerId, lostArea, remainingArea);

            return new TerritoryResetResult
            {
                Success = true,
                RemainingArea = remainingArea,
                NewSpawnArea = spawnPoint,
                LostArea = lostArea
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "重置玩家领地失败 - GameId: {GameId}, PlayerId: {PlayerId}", gameId, playerId);
            return new TerritoryResetResult
            {
                Success = false
            };
        }
    }

    /// <summary>
    /// 获取地图领土分布
    /// </summary>
    public async Task<MapTerritoryDistribution> GetMapTerritoryDistributionAsync(Guid gameId)
    {
        try
        {
            _logger.LogDebug("获取地图领土分布 - GameId: {GameId}", gameId);

            var distribution = new MapTerritoryDistribution
            {
                GameId = gameId,
                Timestamp = DateTime.UtcNow,
                TotalMapArea = GameConstants.MapTotalArea
            };

            // 获取所有玩家
            var playersKey = string.Format(RedisKeys.GamePlayers, gameId);
            var playerIds = await _redisService.GetSetMembersAsync(playersKey);

            var playerTerritories = new List<PlayerTerritoryInfo>();
            decimal totalClaimedArea = 0m;

            foreach (var playerIdStr in playerIds)
            {
                if (Guid.TryParse(playerIdStr, out var playerId))
                {
                    var areaInfo = await CalculatePlayerTerritoryAsync(gameId, playerId);
                    var playerName = await GetPlayerNameAsync(gameId, playerId);
                    var playerColor = await GetPlayerColorAsync(gameId, playerId);
                    var isDrawing = await IsPlayerDrawingAsync(gameId, playerId);
                    
                    var playerInfo = new PlayerTerritoryInfo
                    {
                        PlayerId = playerId,
                        PlayerName = playerName,
                        PlayerColor = playerColor,
                        Area = areaInfo.CurrentArea,
                        Percentage = areaInfo.AreaPercentage,
                        Rank = areaInfo.Rank,
                        Territory = areaInfo.TerritoryBoundary,
                        SpawnPoint = await GetPlayerSpawnPointAsync(gameId, playerId),
                        IsDrawing = isDrawing
                    };

                    if (isDrawing)
                    {
                        playerInfo.CurrentTrail = await GetPlayerCurrentTrailAsync(gameId, playerId);
                    }

                    playerTerritories.Add(playerInfo);
                    totalClaimedArea += areaInfo.CurrentArea;
                }
            }

            // 按面积排序并更新排名
            playerTerritories = playerTerritories.OrderByDescending(p => p.Area).ToList();
            for (int i = 0; i < playerTerritories.Count; i++)
            {
                playerTerritories[i].Rank = i + 1;
            }

            distribution.PlayerTerritories = playerTerritories;
            distribution.ClaimedArea = (float)totalClaimedArea;
            distribution.NeutralArea = GameConstants.MapTotalArea - (float)totalClaimedArea;

            // 检查是否有主导玩家
            if (playerTerritories.Any())
            {
                var topPlayer = playerTerritories.First();
                if (topPlayer.Percentage >= (decimal)(GameConstants.DominantPlayerThreshold * 100))
                {
                    distribution.HasDominantPlayer = true;
                    distribution.DominantPlayerId = topPlayer.PlayerId;
                }
            }

            return distribution;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取地图领土分布失败 - GameId: {GameId}", gameId);
            return new MapTerritoryDistribution
            {
                GameId = gameId,
                Timestamp = DateTime.UtcNow,
                TotalMapArea = GameConstants.MapTotalArea
            };
        }
    }

    /// <summary>
    /// 计算领地征服
    /// </summary>
    public async Task<TerritoryConquestResult> CalculateTerritoryConquestAsync(Guid gameId, Guid attackerId, List<Position> newTerritory)
    {
        try
        {
            _logger.LogDebug("计算领地征服 - GameId: {GameId}, AttackerId: {AttackerId}", gameId, attackerId);

            var result = new TerritoryConquestResult
            {
                Success = true
            };

            // 获取所有其他玩家
            var playersKey = string.Format(RedisKeys.GamePlayers, gameId);
            var playerIds = await _redisService.GetSetMembersAsync(playersKey);

            foreach (var playerIdStr in playerIds)
            {
                if (Guid.TryParse(playerIdStr, out var defenderId) && defenderId != attackerId)
                {
                    // 计算被征服的面积
                    var conqueredArea = await CalculateConqueredAreaAsync(gameId, defenderId, newTerritory);
                    
                    if (conqueredArea > 0)
                    {
                        result.ConqueredPlayers.Add(defenderId);
                        result.TotalConqueredArea += (decimal)conqueredArea;
                        
                        result.Conquests.Add(new TerritoryConquest
                        {
                            ConqueredPlayerId = defenderId,
                            ConqueredArea = (decimal)conqueredArea,
                            ConqueredTerritory = await GetConqueredTerritoryBoundaryAsync(gameId, defenderId, newTerritory)
                        });

                        // 从被征服玩家的领地中移除被征服部分
                        await RemoveConqueredTerritoryAsync(gameId, defenderId, newTerritory);
                    }
                }
            }

            // 计算攻击者的新总面积
            var attackerCurrentArea = await CalculatePlayerTerritoryAsync(gameId, attackerId);
            var newTerritoryArea = CalculatePolygonArea(newTerritory);
            result.NewTotalArea = attackerCurrentArea.CurrentArea + (decimal)newTerritoryArea + result.TotalConqueredArea;

            _logger.LogDebug("领地征服计算完成 - GameId: {GameId}, AttackerId: {AttackerId}, ConqueredPlayers: {Count}, ConqueredArea: {Area:F1}", 
                gameId, attackerId, result.ConqueredPlayers.Count, result.TotalConqueredArea);

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "计算领地征服失败 - GameId: {GameId}, AttackerId: {AttackerId}", gameId, attackerId);
            return new TerritoryConquestResult
            {
                Success = false
            };
        }
    }

    /// <summary>
    /// 检查画线长度限制
    /// </summary>
    public async Task<TrailLengthCheckResult> CheckTrailLengthLimitAsync(Guid gameId, Guid playerId)
    {
        try
        {
            var trailKey = string.Format(RedisKeys.PlayerTrail, gameId, playerId);
            var trailData = await _redisService.ListRangeAsync(trailKey);
            
            var trail = trailData.Select(data =>
            {
                try
                {
                    var trailPoint = JsonSerializer.Deserialize<TrailPoint>(data);
                    return trailPoint?.Position ?? new Position();
                }
                catch
                {
                    return new Position();
                }
            }).ToList();

            var currentLength = CalculateTrailLength(trail);
            var remainingLength = GameConstants.MaxTrailLength - currentLength;
            var isNearLimit = currentLength / GameConstants.MaxTrailLength > GameConstants.NearLimitThreshold;

            return new TrailLengthCheckResult
            {
                IsWithinLimit = currentLength <= GameConstants.MaxTrailLength,
                CurrentLength = currentLength,
                MaxLength = GameConstants.MaxTrailLength,
                RemainingLength = Math.Max(0, remainingLength),
                IsNearLimit = isNearLimit
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "检查画线长度限制失败 - GameId: {GameId}, PlayerId: {PlayerId}", gameId, playerId);
            return new TrailLengthCheckResult
            {
                IsWithinLimit = false,
                MaxLength = GameConstants.MaxTrailLength
            };
        }
    }

    /// <summary>
    /// 应用地图缩圈效果
    /// </summary>
    public async Task<MapShrinkResult> ApplyMapShrinkAsync(Guid gameId, float shrinkRadius)
    {
        try
        {
            _logger.LogInformation("应用地图缩圈效果 - GameId: {GameId}, ShrinkRadius: {Radius}", gameId, shrinkRadius);

            var result = new MapShrinkResult
            {
                Success = true,
                NewMapRadius = shrinkRadius
            };

            // 获取所有玩家
            var playersKey = string.Format(RedisKeys.GamePlayers, gameId);
            var playerIds = await _redisService.GetSetMembersAsync(playersKey);

            foreach (var playerIdStr in playerIds)
            {
                if (Guid.TryParse(playerIdStr, out var playerId))
                {
                    var areaLoss = await CalculateAreaLossFromShrink(gameId, playerId, shrinkRadius);
                    if (areaLoss.AreaLost > 0)
                    {
                        result.AffectedPlayers.Add(playerId);
                        result.TotalAreaLost += areaLoss.AreaLost;
                        result.PlayerLosses.Add(areaLoss);

                        // 更新玩家领地面积
                        var stateKey = string.Format(RedisKeys.PlayerState, gameId, playerId);
                        await _redisService.SetHashAsync(stateKey, "territory_area", areaLoss.RemainingArea.ToString("F2"));
                    }
                }
            }

            _logger.LogInformation("地图缩圈应用完成 - GameId: {GameId}, AffectedPlayers: {Count}, TotalAreaLost: {Area:F1}", 
                gameId, result.AffectedPlayers.Count, result.TotalAreaLost);

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "应用地图缩圈效果失败 - GameId: {GameId}", gameId);
            return new MapShrinkResult
            {
                Success = false
            };
        }
    }

    /// <summary>
    /// 检查提前结束条件
    /// </summary>
    public async Task<EarlyEndCheckResult> CheckEarlyEndConditionAsync(Guid gameId)
    {
        try
        {
            _logger.LogDebug("检查提前结束条件 - GameId: {GameId}", gameId);

            var distribution = await GetMapTerritoryDistributionAsync(gameId);

            // 检查是否有主导玩家
            if (distribution.HasDominantPlayer)
            {
                var dominantPlayer = distribution.PlayerTerritories.First();
                return new EarlyEndCheckResult
                {
                    CanEndEarly = true,
                    DominantPlayerId = dominantPlayer.PlayerId,
                    DominantPlayerPercentage = dominantPlayer.Percentage,
                    Reason = EarlyEndReason.DominantPlayer
                };
            }

            // 检查是否只剩一个存活玩家
            var alivePlayers = await GetAlivePlayersCountAsync(gameId);
            if (alivePlayers <= 1)
            {
                return new EarlyEndCheckResult
                {
                    CanEndEarly = true,
                    Reason = EarlyEndReason.LastPlayerStanding
                };
            }

            return new EarlyEndCheckResult
            {
                CanEndEarly = false,
                Reason = EarlyEndReason.None
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "检查提前结束条件失败 - GameId: {GameId}", gameId);
            return new EarlyEndCheckResult
            {
                CanEndEarly = false,
                Reason = EarlyEndReason.None
            };
        }
    }

    /// <summary>
    /// 获取游戏领地概览
    /// 获取游戏中所有玩家的领地分布和统计信息
    /// </summary>
    public async Task<TerritoryOverviewResult> GetGameTerritoryOverviewAsync(Guid gameId)
    {
        try
        {
            _logger.LogDebug("获取游戏领地概览 - GameId: {GameId}", gameId);

            var result = new TerritoryOverviewResult
            {
                Success = true,
                GameId = gameId,
                Timestamp = DateTime.UtcNow,
                TotalMapArea = GameConstants.MapTotalArea
            };

            // 获取所有玩家
            var playersKey = string.Format(RedisKeys.GamePlayers, gameId);
            var playerIds = await _redisService.GetSetMembersAsync(playersKey);

            var playerStatsList = new List<PlayerTerritoryStats>();
            decimal totalClaimedArea = 0m;

            foreach (var playerIdStr in playerIds)
            {
                if (Guid.TryParse(playerIdStr, out var playerId))
                {
                    // 获取玩家领地信息
                    var areaInfo = await CalculatePlayerTerritoryAsync(gameId, playerId);
                    var playerName = await GetPlayerNameAsync(gameId, playerId);
                    var playerColor = await GetPlayerColorAsync(gameId, playerId);
                    var isAlive = await IsPlayerAliveAsync(gameId, playerId);
                    var spawnPoint = await GetPlayerSpawnPointAsync(gameId, playerId);

                    var playerStats = new PlayerTerritoryStats
                    {
                        PlayerId = playerId,
                        PlayerName = playerName,
                        PlayerColor = playerColor,
                        Area = areaInfo.CurrentArea,
                        Percentage = areaInfo.AreaPercentage,
                        Rank = areaInfo.Rank,
                        IsAlive = isAlive,
                        SpawnPoint = spawnPoint,
                        TerritoryBoundary = areaInfo.TerritoryBoundary
                    };

                    playerStatsList.Add(playerStats);
                    totalClaimedArea += areaInfo.CurrentArea;
                }
            }

            // 按面积排序并更新排名
            playerStatsList = playerStatsList.OrderByDescending(p => p.Area).ToList();
            for (int i = 0; i < playerStatsList.Count; i++)
            {
                playerStatsList[i].Rank = i + 1;
            }

            result.PlayerStats = playerStatsList;
            result.ClaimedArea = (float)totalClaimedArea;

            _logger.LogDebug("获取游戏领地概览成功 - GameId: {GameId}, Players: {PlayerCount}, ClaimedArea: {Area:F1}", 
                gameId, playerStatsList.Count, totalClaimedArea);

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取游戏领地概览失败 - GameId: {GameId}", gameId);
            return new TerritoryOverviewResult
            {
                Success = false,
                GameId = gameId,
                Timestamp = DateTime.UtcNow,
                TotalMapArea = GameConstants.MapTotalArea,
                Errors = { "获取领地概览时发生内部错误" }
            };
        }
    }

    #region 私有辅助方法

    /// <summary>
    /// 检查玩家是否存活
    /// </summary>
    private async Task<bool> IsPlayerAliveAsync(Guid gameId, Guid playerId)
    {
        try
        {
            var stateKey = string.Format(RedisKeys.PlayerState, gameId, playerId);
            var state = await _redisService.HashGetAsync(stateKey, "state");
            return state != PlayerDrawingState.Dead.ToString();
        }
        catch
        {
            return true; // 默认认为存活
        }
    }

    /// <summary>
    /// 轨迹点数据结构
    /// </summary>
    private class TrailPoint
    {
        public Position Position { get; set; } = new();
        public DateTime Timestamp { get; set; }
        public int SequenceNumber { get; set; }
    }

    /// <summary>
    /// 领地多边形数据结构
    /// </summary>
    private class TerritoryPolygon
    {
        public Guid Id { get; set; }
        public List<Position> Boundary { get; set; } = new();
        public float Area { get; set; }
        public DateTime CapturedTime { get; set; }
    }

    /// <summary>
    /// 计算轨迹长度
    /// </summary>
    private static float CalculateTrailLength(List<Position> trail)
    {
        if (trail.Count < 2) return 0f;

        float totalLength = 0f;
        for (int i = 1; i < trail.Count; i++)
        {
            totalLength += CalculateDistance(trail[i - 1], trail[i]);
        }
        return totalLength;
    }

    /// <summary>
    /// 计算两点间距离
    /// </summary>
    private static float CalculateDistance(Position pos1, Position pos2)
    {
        var dx = pos2.X - pos1.X;
        var dy = pos2.Y - pos1.Y;
        return (float)Math.Sqrt(dx * dx + dy * dy);
    }

    /// <summary>
    /// 检查是否为有效闭合区域
    /// </summary>
    private static bool IsValidClosedArea(List<Position> polygon)
    {
        if (polygon.Count < 3) return false;

        // 简化检查：起点和终点距离是否足够近，或者终点是否与某个中间点接近
        var startPoint = polygon.First();
        var endPoint = polygon.Last();
        
        return CalculateDistance(startPoint, endPoint) < 50f; // 50像素内认为闭合
    }

    /// <summary>
    /// 计算多边形面积（Shoelace公式）
    /// </summary>
    private static float CalculatePolygonArea(List<Position> polygon)
    {
        if (polygon.Count < 3) return 0f;

        float area = 0f;
        int j = polygon.Count - 1;

        for (int i = 0; i < polygon.Count; i++)
        {
            area += (polygon[j].X + polygon[i].X) * (polygon[j].Y - polygon[i].Y);
            j = i;
        }

        return Math.Abs(area) / 2f;
    }

    /// <summary>
    /// 保存玩家领地
    /// </summary>
    private async Task SavePlayerTerritoryAsync(Guid gameId, Guid playerId, List<Position> boundary, float area)
    {
        var territoryKey = string.Format(RedisKeys.PlayerTerritory, gameId, playerId);
        var territory = new TerritoryPolygon
        {
            Id = Guid.NewGuid(),
            Boundary = boundary,
            Area = area,
            CapturedTime = DateTime.UtcNow
        };

        await _redisService.ListRightPushAsync(territoryKey, JsonSerializer.Serialize(territory));
    }

    /// <summary>
    /// 检查位置是否在玩家领地内
    /// </summary>
    private async Task<bool> IsPositionInPlayerTerritoryAsync(Guid gameId, Guid playerId, Position position)
    {
        var territoryKey = string.Format(RedisKeys.PlayerTerritory, gameId, playerId);
        var territoriesData = await _redisService.ListRangeAsync(territoryKey);

        foreach (var territoryData in territoriesData)
        {
            try
            {
                var territory = JsonSerializer.Deserialize<TerritoryPolygon>(territoryData);
                if (territory != null && IsPointInPolygon(position, territory.Boundary))
                {
                    return true;
                }
            }
            catch
            {
                // 忽略无效数据
            }
        }

        return false;
    }

    /// <summary>
    /// 点在多边形内判断（射线法）
    /// </summary>
    private static bool IsPointInPolygon(Position point, List<Position> polygon)
    {
        if (polygon.Count < 3) return false;

        bool inside = false;
        int j = polygon.Count - 1;

        for (int i = 0; i < polygon.Count; i++)
        {
            var pi = polygon[i];
            var pj = polygon[j];

            if (((pi.Y > point.Y) != (pj.Y > point.Y)) &&
                (point.X < (pj.X - pi.X) * (point.Y - pi.Y) / (pj.Y - pi.Y) + pi.X))
            {
                inside = !inside;
            }
            j = i;
        }

        return inside;
    }

    // 其他辅助方法的简化实现...
    private async Task<string> GetPlayerColorAsync(Guid gameId, Guid playerId)
    {
        var stateKey = string.Format(RedisKeys.PlayerState, gameId, playerId);
        return await _redisService.HashGetAsync(stateKey, "player_color") ?? "red";
    }

    private async Task<int> GetPlayerRankAsync(Guid gameId, Guid playerId)
    {
        var stateKey = string.Format(RedisKeys.PlayerState, gameId, playerId);
        var rankStr = await _redisService.HashGetAsync(stateKey, "current_rank");
        return int.TryParse(rankStr, out var rank) ? rank : 0;
    }

    private Task<bool> IsSpawnAreaAsync(Guid gameId, Position position)
    {
        // 简化实现：检查是否在地图边缘附近
        var isSpawnArea = position.X < 50 || position.Y < 50 || 
                         position.X > GameConstants.MapSize - 50 || 
                         position.Y > GameConstants.MapSize - 50;
        return Task.FromResult(isSpawnArea);
    }

    private Task<float> CalculateDistanceToNearestBoundaryAsync(Guid gameId, Position position)
    {
        // 简化实现：返回到地图边界的距离
        var distanceToEdges = new[]
        {
            position.X, // 左边界
            position.Y, // 上边界
            GameConstants.MapSize - position.X, // 右边界
            GameConstants.MapSize - position.Y  // 下边界
        };
        return Task.FromResult(distanceToEdges.Min());
    }

    private async Task<Position> GetPlayerSpawnPointAsync(Guid gameId, Guid playerId)
    {
        var stateKey = string.Format(RedisKeys.PlayerState, gameId, playerId);
        var spawnPointStr = await _redisService.HashGetAsync(stateKey, "spawn_point");
        
        if (!string.IsNullOrEmpty(spawnPointStr))
        {
            try
            {
                return JsonSerializer.Deserialize<Position>(spawnPointStr) ?? new Position();
            }
            catch
            {
                // 忽略解析错误
            }
        }

        return new Position { X = 500, Y = 500 }; // 默认中心点
    }

    private static List<Position> CreateSafeArea(Position center, float size)
    {
        var halfSize = size / 2;
        return new List<Position>
        {
            new() { X = center.X - halfSize, Y = center.Y - halfSize },
            new() { X = center.X + halfSize, Y = center.Y - halfSize },
            new() { X = center.X + halfSize, Y = center.Y + halfSize },
            new() { X = center.X - halfSize, Y = center.Y + halfSize }
        };
    }

    private async Task<string> GetPlayerNameAsync(Guid gameId, Guid playerId)
    {
        var stateKey = string.Format(RedisKeys.PlayerState, gameId, playerId);
        return await _redisService.HashGetAsync(stateKey, "player_name") ?? "Unknown";
    }

    private async Task<bool> IsPlayerDrawingAsync(Guid gameId, Guid playerId)
    {
        var stateKey = string.Format(RedisKeys.PlayerState, gameId, playerId);
        var state = await _redisService.HashGetAsync(stateKey, "state");
        return state == PlayerDrawingState.Drawing.ToString();
    }

    private async Task<List<Position>> GetPlayerCurrentTrailAsync(Guid gameId, Guid playerId)
    {
        var trailKey = string.Format(RedisKeys.PlayerTrail, gameId, playerId);
        var trailData = await _redisService.ListRangeAsync(trailKey);
        
        return trailData.Select(data =>
        {
            try
            {
                var trailPoint = JsonSerializer.Deserialize<TrailPoint>(data);
                return trailPoint?.Position ?? new Position();
            }
            catch
            {
                return new Position();
            }
        }).ToList();
    }

    // 更多简化的辅助方法...
    private Task<float> CalculateConqueredAreaAsync(Guid gameId, Guid defenderId, List<Position> attackerTerritory)
    {
        // 简化实现：计算被包围的面积
        return Task.FromResult(0f); // 实际需要复杂的几何计算
    }

    private Task<List<Position>> GetConqueredTerritoryBoundaryAsync(Guid gameId, Guid defenderId, List<Position> attackerTerritory)
    {
        return Task.FromResult(new List<Position>()); // 简化实现
    }

    private Task RemoveConqueredTerritoryAsync(Guid gameId, Guid defenderId, List<Position> attackerTerritory)
    {
        // 简化实现：移除被征服的领地部分
        return Task.CompletedTask;
    }

    private async Task<PlayerAreaLoss> CalculateAreaLossFromShrink(Guid gameId, Guid playerId, float shrinkRadius)
    {
        var currentArea = await CalculatePlayerTerritoryAsync(gameId, playerId);
        var lostArea = currentArea.CurrentArea * 0.1m; // 简化：损失10%
        
        return new PlayerAreaLoss
        {
            PlayerId = playerId,
            AreaLost = lostArea,
            RemainingArea = currentArea.CurrentArea - lostArea
        };
    }

    private async Task<int> GetAlivePlayersCountAsync(Guid gameId)
    {
        var playersKey = string.Format(RedisKeys.GamePlayers, gameId);
        var playerIds = await _redisService.GetSetMembersAsync(playersKey);
        
        int aliveCount = 0;
        foreach (var playerIdStr in playerIds)
        {
            if (Guid.TryParse(playerIdStr, out var playerId))
            {
                var stateKey = string.Format(RedisKeys.PlayerState, gameId, playerId);
                var state = await _redisService.HashGetAsync(stateKey, "state");
                if (state != PlayerDrawingState.Dead.ToString())
                {
                    aliveCount++;
                }
            }
        }
        
        return aliveCount;
    }

    #endregion
}
